#include "game.h"
#include "ui_game.h"

Game::Game(QWidget *parent, QString str) :
    QDialog(parent),
    ui(new Ui::Game)
{
    ui->setupUi(this);

    MainMenu *m = dynamic_cast<MainMenu*>(this->parent());
    this->setFixedSize(m->resX, m->resY); //resolution

    file = str;    //file path

    background = new QLabel(this);          //displays level (background)
    background->setGeometry(0,0,1680,1050);
    bkground = new QPixmap("Images\\World1.bmp");
    background->setPixmap(*bkground);
    background->show();

    if(m->hard)
        levelN = 6; //hard mode
    else
        levelN = 1; //easy mode

    x = 10; //start position
    y = 500;
    width = 40;
    height = 41;
    ymomentum =0;
    resY = m->resY;
    airborn = true;

    lvl = new Level(levelN, file); //loads level
    refreshBackground();

    gmTime = new QLabel(this);  //score keeping displays
    gmDeaths = new QLabel(this);
    gmTime->setText("Time: 0");
    gmDeaths->setText("Deaths: 0");
    timeCnt = 0;
    deathCnt = 0;

    gmTime->setGeometry(110,1,100,12);  //score displays
    gmDeaths->setGeometry(10,1,100,12);
    gmTime->show();
    gmDeaths->show();

    btn = new QLabel(this);    // creates Orb
    btn->setGeometry(x,y,width,height);
    orb = new QPixmap("Images\\Orb.gif");   //loads in all Orb pictures
    orb2 = new QPixmap("Images\\Orb2.gif");
    orb3 = new QPixmap("Images\\Orb3.gif");

    btn->setPixmap(*orb2);
    btn->show();   //shows orb

    //timer that controls movement
    moveT = new QTimer(this);
    connect(moveT, SIGNAL(timeout()),this, SLOT(moveBtn()));
    moveT->setInterval(30);

    //timer that controls gmTime
    secT = new QTimer(this);
    connect(secT, SIGNAL(timeout()),this, SLOT(incTime()));
    secT->setInterval(1000);

    //timer that delays death
    delayT = new QTimer(this);
    connect(delayT, SIGNAL(timeout()),this, SLOT(delayDeath()));
    delayT->setInterval(1000);
}

Game::~Game()
{
    delete ui;
}

void Game::StartTimers(){ //starts game
    secT->start();
    moveT->start();
}
void Game::StopTimers(){ //stops game
    secT->stop();
    moveT->stop();
    delayT->stop();
}

void Game::LoadGame(int level,int X,int Y,int ymom,int time,int death){
    levelN = level;       //changes level
    lvl->changeLevel(levelN);  //loads level

    x = X;   //changes position
    y = Y;
    ymomentum = ymom;  //changes speed

    timeCnt = time;    //changes score
    deathCnt = death;
    QString *str = new QString();
    *str = "Time: " + QString::number(timeCnt);
    gmTime->setText(*str);
    *str = "Deaths: " + QString::number(deathCnt);
    gmDeaths->setText(*str);

    refreshBackground();  //displays level

    this->show();
}

void Game::refreshBackground(){   //changes the level displayed
    QString *str = new QString();
    *str = "Images\\World" + QString::number(levelN) + ".bmp";
    bkground = new QPixmap(*str);
    background->setPixmap(*bkground);
}

void Game::incTime(){   //increments the game timer
    QString *str = new QString();
    *str = "Time: " + QString::number(timeCnt);
    gmTime->setText(*str);
    timeCnt ++;
}

void Game::incDeaths() {   //increments the death counter for spikes
    moveT->stop();
    if(!dead){
        width = height = 80;
        x -= 16;
        y -= 16;
        deathCnt ++;
        QString *str = new QString();
        *str = "Deaths: " + QString::number(deathCnt);
        gmDeaths->setText(*str);
        dead = true;
    }
   btn->setGeometry(x, y, width, height);
   btn->setPixmap(*orb3);

   delayT->start();
}

void Game::delayDeath(){  //resets location after a delay
   delayT->stop();
   x=10;
   y=10;
   width = 40;
   height = 41;
   ymomentum = 0;
   dead = false;
   moveT->start();
}

void Game::fallDeaths(){  //increments the death counter for falling
    deathCnt ++;
    QString *str = new QString();
    *str = "Deaths: " + QString::number(deathCnt);
    gmDeaths->setText(*str);
    x=10;
    y=10;
    ymomentum = 0;
}

void Game::moveBtn() {  //movement logic

    if(!dead){
        if(GetKeyState('W') < 0){  //jumps
            if(!airborn){
              ymomentum = 13; //sets fall speed
              airborn = true; //prohibits continuous jumping
            }
        }
        rw = lvl->getRW(x,y);   //gets right wall
        lw = lvl->getLW(x,y);   //gets left wall

        if (GetKeyState('D') < 0) {   //checks for movement right
            x += 5;
        }else if(GetKeyState('A') < 0){  //checks for movement left
            x -= 5;
        }
        flY = lvl->getFlY(x,y);  // gets floor for y calculations
        flX = lvl->getFlX(x,y);  // gets floor for x calculations
        top = lvl->getTop(x,y);  // gets ceiling


        //checks x bounds
        if(x > rw-40 && flX-y <= 40 && flX-y > 20 && ymomentum < 0){
            x = rw-sqrt(400-(flX-y-20)*(flX-y-20))-26; //"rolling" off right edges while falling
        }else if(x > rw-40 && flX-y <= 40 && flX-y > 20 && ymomentum >= 0){
            x = rw-sqrt(400-(flX-y-20)*(flX-y-20))-19; //"rolling" over right edges while jumping
        }else if(x > rw-40){
            x = rw-40; //regular right edge
        }else if(x < lw && flX-y <= 40 && flX-y > 20 && ymomentum < 0){
            x = lw+sqrt(400-(flX-y-20)*(flX-y-20))-14;  //"rolling" off left edges while falling
        }else if(x < lw && flX-y <= 40 && flX-y > 20 && ymomentum >= 0){
            x = lw+sqrt(400-(flX-y-20)*(flX-y-20))-21;  //"rolling" over left edges while jumping
        }else if(x < lw){
            x = lw;  //regular left edge
        }

        ymomentum-=1; //fall speed
        y-=ymomentum; //changes y by fall speed
        airborn =true; //prohibits jumping

        //checks y bounds
        if(ymomentum <= 0){   //while falling
            if(y > resY +10){   //below level (down a pit)
              fallDeaths();  //death sequence
            }else if(y>= flY - 41){ //if y is lower than allowed, puts the orb on the ground
                ymomentum = -1; //resets fall speed
                y = flY-41;
                airborn = false; //allows jumping
                btn->setPixmap(*orb); //Orb with shawdow
            }else
                btn->setPixmap(*orb2); //Orb without shadow
        }else{    //while jumping
            btn->setPixmap(*orb2); //Orb without shadow
            if(y < top){   //if y is higher than allowed, puts the orb below the ceiling
                ymomentum = -1;  //sets momentum downward
                y = top -1 ;
            }
        }

        if(lvl->getSpikes(x,y)){ //checks for spikes
            incDeaths();
        }else{
            //moves Orb to proper location
            btn->setGeometry(x,y,width,height);
        }
    }else
        incDeaths();
}

void Game::keyPressEvent(QKeyEvent *event){

    // checks for key events outside of movement keys
    if(event->key() == Qt::Key_P){  //pauses the game
        StopTimers();
        PauseMenu *pm = new PauseMenu(this);
        pm->show();

    }else if(event->key() == Qt::Key_E){  //exits the level if in bounds of exit
        if(x>= 740 && y>= 490){
            if(levelN != 5 && levelN != 10){  //goes to next level if not at level 5 or 10
                ++levelN;
                lvl->changeLevel(levelN);
                refreshBackground();
                x =y =10;
            }else{  //ends game and shows score
                StopTimers();
                End *end = new End(this, timeCnt, deathCnt);
                end->show();
            }
        }
    }
    if(event->key() == Qt::Key_F && dynamic_cast<MainMenu*>(this->parent())->cheat){
        //takes you to the end of the level if in cheat mode
       x = 740;
       y = 490;
   }
}
